package com.wang.springbootinit.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wang.springbootinit.common.ErrorCode;
import com.wang.springbootinit.exception.BusinessException;
import com.wang.springbootinit.mapper.ExemptionMapper;
import com.wang.springbootinit.model.dto.ExemptionQueryDTO;
import com.wang.springbootinit.model.dto.ExemptionReviewDTO;
import com.wang.springbootinit.model.entity.Exemption;
import com.wang.springbootinit.model.entity.Student;
import com.wang.springbootinit.model.entity.User;
import com.wang.springbootinit.model.vo.ExemptionVO;
import com.wang.springbootinit.model.vo.LoginUserVO;
import com.wang.springbootinit.service.ExemptionService;
import com.wang.springbootinit.service.StudentService;
import com.wang.springbootinit.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toMap;

/**
 * 免修申请服务实现类
 * 处理学生免修申请的相关业务逻辑
 */
@Service
@Slf4j
public class ExemptionServiceImpl extends ServiceImpl<ExemptionMapper, Exemption> implements ExemptionService {
    @Autowired
    private ExemptionMapper exemptionMapper;

    @Autowired
    private StudentService studentService;

    @Autowired
    private UserService userService;

    /**
     * 提交免修申请
     * @param exemption 免修申请信息
     * @return 提交是否成功
     */
    @Override
    public boolean submitExemption(Exemption exemption,HttpServletRequest request) {
        Student loginStudent = userService.getLoginStudent(request);
        exemption.setApplyTime(LocalDateTime.now());
        exemption.setApplyStatus(0); // 设置为待审核状态
        exemption.setReviewTime(null);
        exemption.setStudentId(loginStudent.getId());
        return save(exemption);
    }

    /**
     * 审核免修申请
     * @param reviewDTO 审核信息，包含审核结果和评论
     * @return 审核是否成功
     * @throws BusinessException 当申请不存在或已处理时抛出异常
     */
    @Override
    public boolean reviewExemption(ExemptionReviewDTO reviewDTO,HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        Exemption exemption = exemptionMapper.selectById(reviewDTO.getExemptionId());
        if (exemption == null) {
            throw new BusinessException("申请不存在");
        }
        if (exemption.getApplyStatus() != 0) {
            throw new BusinessException("该申请已被处理");
        }

        Exemption update = new Exemption();
        update.setExemptionId(reviewDTO.getExemptionId());
        update.setApplyStatus(reviewDTO.getApplyStatus());
        update.setReviewComment(reviewDTO.getReviewComment());
        update.setReviewTime(LocalDateTime.now());
        update.setReviewBy(loginUser.getUserName());
        
        int result = exemptionMapper.updateById(update);
        if (result > 0) {
            return true;
        }
        throw new BusinessException("审核失败");
    }

    /**
     * 分页查询免修申请
     * @param queryDTO 查询条件，包含学生ID、申请状态、时间范围等
     * @return 免修申请分页结果
     */
    @Override
    public Page<ExemptionVO> getExemptionPage(ExemptionQueryDTO queryDTO) {
        LambdaQueryWrapper<Exemption> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(queryDTO.getApplyStatus() != null,
                   Exemption::getApplyStatus, queryDTO.getApplyStatus())
               .ge(queryDTO.getStartTime() != null, 
                   Exemption::getApplyTime, queryDTO.getStartTime())
               .le(queryDTO.getEndTime() != null, 
                   Exemption::getApplyTime, queryDTO.getEndTime())
               .orderByDesc(Exemption::getApplyTime);
        if(StrUtil.isNotEmpty(queryDTO.getStudentNumber())){
            Student student = studentService.getStudentByNumber(queryDTO.getStudentNumber());
            if(ObjectUtil.isNull(student)){
                return new Page<>();
            }
            if(ObjectUtil.isNotNull(student)){
                wrapper.eq(Exemption::getStudentId,student.getId());
            }
        }

        Page<Exemption> page = new Page<>(queryDTO.getCurrent(), queryDTO.getPageSize());
        Page<Exemption> selectedPage = exemptionMapper.selectPage(page, wrapper);
        if(ObjectUtil.isNotNull(selectedPage)){
            if(CollUtil.isEmpty(selectedPage.getRecords())){
                return new Page<>();
            }
            List<Exemption> exemptionList = selectedPage.getRecords();
            List<Long> studentIds = exemptionList.stream().map(Exemption::getStudentId).collect(Collectors.toList());
            List<Student> studentList = studentService.listByIds(studentIds);
            Map<Long, Student> studentMap = studentList.stream().collect(toMap(Student::getId, Function.identity(), (k1, k2) -> k1));

            List<ExemptionVO> exemptionVOS = exemptionList.stream().map(item -> {
                ExemptionVO exemptionVO = new ExemptionVO();
                BeanUtils.copyProperties(item, exemptionVO);
                Student student = studentMap.get(item.getStudentId());
                if (ObjectUtil.isNotNull(student)) {
                    exemptionVO.setStudentNumber(student.getStudentNumber());
                }
                return exemptionVO;
            }).collect(Collectors.toList());

            Page<ExemptionVO> voPage = new Page<>();
            voPage.setSize(selectedPage.getSize());
            voPage.setTotal(selectedPage.getTotal());
            voPage.setSize(selectedPage.getSize());
            voPage.setCurrent(selectedPage.getCurrent());
            voPage.setRecords(exemptionVOS);
            return voPage;
        }
        throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
    }

    /**
     * 根据ID获取免修申请详情
     * @param exemptionId 免修申请ID
     * @return 免修申请信息
     */
    @Override
    public Exemption getExemptionById(Long exemptionId) {
        return null;
    }

    /**
     * 获取指定学生的所有免修申请
     * @param studentId 学生ID
     * @return 该学生的免修申请列表
     */
    @Override
    public List<Exemption> getMyExemptions(Long studentId) {
        return Collections.emptyList();
    }

    /**
     * 审核
     * @param reviewDTO
     * @return
     */
    @Override
    public boolean audit(ExemptionReviewDTO reviewDTO) {
        if(ObjectUtil.isNull(reviewDTO) || ObjectUtil.isNull(reviewDTO.getExemptionId())){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        LambdaUpdateWrapper<Exemption> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Exemption::getExemptionId,reviewDTO.getExemptionId());
        updateWrapper.set(Exemption::getApplyTime, DateUtil.now());
        updateWrapper.set(Exemption::getApplyStatus,reviewDTO.getApplyStatus());
        return update(updateWrapper);
    }

    @Override
    public List<ExemptionVO> getCurrentList(HttpServletRequest request) {
        Student loginStudent = userService.getLoginStudent(request);
        LambdaQueryWrapper<Exemption> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Exemption::getStudentId,loginStudent.getId());
        List<Exemption> list = list(queryWrapper);
        if(CollUtil.isEmpty(list)){
            return new ArrayList<>();
        }
        return list.stream().map(item -> {
            ExemptionVO exemptionVO = new ExemptionVO();
            BeanUtils.copyProperties(item,exemptionVO);
            exemptionVO.setStudentNumber(loginStudent.getStudentNumber());
            return exemptionVO;
        }).collect(Collectors.toList());
    }
} 